home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / ip / ppp / mac / macppp1.1.3-src.hqx / MacPPP1.1.3-src / fsm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-10  |  15.4 KB  |  655 lines

  1. /*
  2.  * fsm.c -- PPP Finite State Machine
  3.  *
  4.  * Copyright 1991-1992 William Allen Simpson
  5.  *  Licensed for non-profit non-commercial distribution
  6.  *  in Merit's PPP LAP for MacTCP
  7.  *
  8.  * Copyright 1992-1993 Merit Network, Inc. and The Regents of the
  9.  *  University of Michigan.  Usage of this source code is restricted
  10.  *  to non-profit, non-commercial purposes.  The source is provided
  11.  *  "as-is", without warranty.
  12.  *
  13.  * This code has been derived solely from the Jan 1991 public
  14.  *  domain release of PPP included in Phil Karn's KA9Q.
  15.  */
  16.  
  17. #include "ppp.h"
  18.  
  19. /* Convert header in host form to network form */
  20. void htoncnf(struct config_hdr *cnf, struct bufheader *bufptr)
  21. {
  22.     register char *cp;
  23.  
  24.     /* Prepend bytes for LCP/IPCP header */
  25.     cp = (bufptr->dataptr -= CONFIG_HDR_LEN);
  26.     bufptr->length += CONFIG_HDR_LEN;
  27.  
  28.     /* Load header with proper values */
  29.     *cp++ = cnf->code;
  30.     *cp++ = cnf->id;
  31.     put16(cp, cnf->len);
  32. }
  33.  
  34. /* Extract header from incoming packet */
  35. int
  36. ntohcnf(struct config_hdr *cnf, struct bufheader *bufptr)
  37. {
  38.     char cnfb[CONFIG_HDR_LEN];
  39.     register char *ptr = cnfb;
  40.  
  41.     if ( yankbuf( bufptr, ptr, CONFIG_HDR_LEN ) < CONFIG_HDR_LEN )
  42.         return -1;
  43.  
  44.     cnf->code = *ptr++;
  45.     cnf->id = *ptr++;
  46.     cnf->len = get16(ptr);
  47.     return 0;
  48. }
  49.  
  50. /* Extract configuration option header */
  51. int
  52. ntohopt(struct option_hdr *opt, struct bufheader *bufptr)
  53. {
  54.     char optb[OPTION_HDR_LEN];
  55.  
  56.     if ( yankbuf( bufptr, optb, OPTION_HDR_LEN ) < OPTION_HDR_LEN )
  57.         return -1;
  58.  
  59.     opt->type = optb[0];
  60.     opt->len = optb[1];
  61.     return 0;
  62. }
  63.  
  64. /* Set a timer in case an expected event does not occur */
  65. void
  66. fsm_timer(fsm_p)
  67. struct fsm_s *fsm_p;
  68. {
  69.     start_timer( &(fsm_p->timer) );
  70. }
  71.  
  72. /* Send a packet to the remote host */
  73. int
  74. fsm_send(struct fsm_s *fsm_p, b_8 code, b_8 id, struct bufheader *bufptr)
  75. {
  76.     LapInfo *lap = fsm_p->lap;
  77.     struct config_hdr hdr;
  78.     void *dummy = nil;        /* dummy ptr to indicate LCP echo req */
  79.  
  80.     if (bufptr == nil)
  81.         return -1;            /* Must pass a bufptr */
  82.  
  83.     switch( hdr.code = code ) {
  84.     case CONFIG_REQ:
  85.     case TERM_REQ:
  86.     case ECHO_REQ:
  87.         /* Save ID field for match against replies from remote host */
  88.         fsm_p->lastid = lap->ppp_id;
  89.         /* fallthru */
  90.     case PROT_REJ:
  91.     case DISCARD_REQ:
  92.         /* Use a unique ID field value */
  93.         hdr.id = lap->ppp_id++;
  94.         break;
  95.  
  96.     default:    /* CONFIG_ACK CONFIG_NAK CONFIG_REJ TERM_ACK CODE_REJ ECHO_REPLY */
  97.         /* Use ID sent by remote host */
  98.         hdr.id = id;
  99.         break;
  100.     }
  101.  
  102.     switch( code ) {
  103.     case ECHO_REQ:
  104.         dummy = bufptr;            /* special hack for LCP echo requests */
  105.         /* fall thru */
  106.     case DISCARD_REQ:
  107.         makeroom(bufptr, 4);    /* make space for magic number */
  108.         /* fall thru */
  109.     case ECHO_REPLY:            /* put our magic number here */
  110.         put32(bufptr->dataptr,
  111.             lap->lcp_i.local.work.lcp_option.magic_number);
  112.     };
  113.  
  114.     hdr.len = bufptr->length + CONFIG_HDR_LEN;
  115.  
  116.     /* Prepend header to packet data */
  117.     htoncnf(&hdr,bufptr);            /* prepend control protocol header */
  118.     htonppp(lap, fsm_p->pdc.protocol, bufptr);    /* prepend ppp header */
  119.     QueueFrame ( lap, bufptr, dummy );
  120.     return 0;
  121. }
  122.  
  123. /* Send a configuration request */
  124. int
  125. fsm_sendreq(fsm_p)
  126. struct fsm_s *fsm_p;
  127. {
  128.     struct bufheader *bufptr;
  129.  
  130.     if ( fsm_p->retry <= 0 )
  131.         return -1;
  132.  
  133.     fsm_p->retry--;
  134.     fsm_timer(fsm_p);
  135.  
  136.     bufptr = makereq(fsm_p);
  137.     return( fsm_send(fsm_p, CONFIG_REQ, 0, bufptr) );
  138. }
  139.  
  140. /* Send a termination request */
  141. static int
  142. fsm_sendtermreq(fsm_p)
  143. struct fsm_s *fsm_p;
  144. {
  145.     if ( fsm_p->retry <= 0 )
  146.         return -1;
  147.  
  148.     fsm_p->retry--;
  149.     fsm_timer(fsm_p);
  150.     return( fsm_send(fsm_p, TERM_REQ, 0, getbuffer()) );
  151. }
  152.  
  153. /* Send Terminate Ack */
  154. static int
  155. fsm_sendtermack(struct fsm_s *fsm_p, b_8 id)
  156. {
  157.     return( fsm_send(fsm_p, TERM_ACK, id, getbuffer()) );
  158. }
  159.  
  160. /* This layer is down */
  161. void
  162. fsm_tld(struct fsm_s *fsm_p)
  163. {
  164.     LapInfo *lap = fsm_p->lap;
  165.  
  166.     if (fsm_p->pdc.fsmi == Lcp) {
  167.         fsm_down( &(lap->ppp_fsm[IPcp]) );    /* IPCP down */
  168.         pap_down( &(lap->ppp_fsm[Pap]) );        /* PAP down */
  169.     }
  170. }
  171.  
  172. /* This layer is finished */
  173. void
  174. fsm_tlf(struct fsm_s *fsm_p)
  175. {
  176.     stop_timer(&(fsm_p->timer));        /* stop the restart timer */
  177.     if (fsm_p->pdc.fsmi == Lcp)
  178.         link_close(fsm_p->lap);        /* can close the link now */
  179.     else    /* IPcp */
  180.         fsm_close( &(fsm_p->lap->ppp_fsm[Lcp]) );    /* close LCP */
  181. }
  182.  
  183. /* This layer up, Configuration negotiation complete */
  184. void
  185. fsm_tlu(struct fsm_s *fsm_p)
  186. {
  187.     LapInfo            *lap = fsm_p->lap;
  188.     struct proto_s    *proto_p = fsm_p->pdv;
  189.  
  190.     stop_timer(&(fsm_p->timer));
  191.     fsm_p->state = fsmOPENED;
  192.     
  193.     if (fsm_p->pdc.fsmi == Lcp) {
  194.         
  195.         /* Set Max Transmission Unit for outgoing packets */
  196.         lap->outMaxPacketSize = proto_p->remote.work.lcp_option.mru;
  197.         if ( (proto_p->remote.want_negotiate & LCP_N_MRU) &&
  198.             lap->outMaxPacketSize > proto_p->remote.want.lcp_option.mru)
  199.             lap->outMaxPacketSize = proto_p->remote.want.lcp_option.mru;
  200.  
  201.         /* set up async ctl maps */
  202.         lap->PPP_RecvACM = proto_p->local.work.lcp_option.accm;
  203.         lap->PPP_XmitACM = proto_p->remote.work.lcp_option.accm;
  204.  
  205.         /* check for authentication */
  206.         lap->ppp_phase = pppAUTHENTICATE;
  207.         lap->ppp_flags &= ~PPP_AP_REMOTE;
  208.     
  209.         if (proto_p->remote.work_negotiate & LCP_N_AUTHENT) {
  210.             if (proto_p->remote.work.lcp_option.authentication == PPP_PAP_PROTOCOL)
  211.                 pap_remote(lap);
  212.         }
  213.         /* re-check for authentication */
  214.         ppp_ready(lap);
  215.     } else {        /* IPcp */
  216.         int rslots = 0;
  217.         int tslots = 0;
  218.  
  219.         if (proto_p->local.work_negotiate & IPCP_N_COMPRESS)
  220.             rslots = proto_p->local.work.ipcp_option.slots;
  221.         if (proto_p->remote.work_negotiate & IPCP_N_COMPRESS) {
  222.             tslots = proto_p->remote.work.ipcp_option.slots;
  223.             if (tslots > IPCP_SLOT_HI)
  224.                 tslots = IPCP_SLOT_HI;
  225.         }
  226.         if ( rslots != 0 || tslots != 0 ) 
  227.             slhc_init( lap, rslots, tslots );
  228.     }
  229. }
  230.  
  231. /* This layer start */
  232. void
  233. fsm_tls(struct fsm_s *fsm_p)
  234. {
  235.     LapInfo *lap = fsm_p->lap;
  236.  
  237.     if (fsm_p->pdc.fsmi == Lcp) {
  238.         if (lap->ppp_phase == pppDEAD)
  239.             link_open(lap);        /* need to open link before we can start */
  240.         else
  241.             lap->ppp_phase = pppESTABLISH;    /* we are in establish phase */
  242.     } else /* IPcp */
  243.         fsm_open( &(lap->ppp_fsm[Lcp]) );    /* start LCP */
  244. }
  245.  
  246. /************************************************************************/
  247. /*            E V E N T   P R O C E S S I N G            */
  248. /************************************************************************/
  249.  
  250. /* Process incoming packet */
  251. void
  252. fsm_proc(struct fsm_s *fsm_p, struct bufheader *bufptr)
  253. {
  254.     struct config_hdr hdr;
  255.     int    result;
  256.     
  257.     switch(fsm_p->state) {
  258.         case fsmINITIAL:
  259.         case fsmSTARTING:
  260.             release(bufptr);
  261.             return;                /* not ready to receive packets yet */
  262.     }
  263.  
  264.     if ( ntohcnf(&hdr, bufptr) == -1 ) {
  265.         PPP_DEBUG_CHECKS("\pshort config packet" );
  266.         release(bufptr);
  267.         return;
  268.     }
  269.  
  270.     hdr.len -= CONFIG_HDR_LEN;        /* Length includes envelope */
  271.     
  272.     switch(hdr.code) {
  273.     case CONFIG_REQ:
  274.         switch(fsm_p->state) {
  275.         case fsmOPENED:        /* Unexpected event? */
  276.             fsm_tld(fsm_p);
  277.             fsm_sendreq(fsm_p);    /* send a new config request */
  278.             fsm_p->state =
  279.             (proc_request(fsm_p, &hdr, bufptr) == 0)
  280.                 ? fsmACK_Sent : fsmREQ_Sent;
  281.             break;
  282.         
  283.         case fsmSTOPPED:
  284.             fsm_reset(fsm_p);    /* init restart counter and reset option vars */
  285.             fsm_sendreq(fsm_p);
  286.             /* fallthru */
  287.         case fsmREQ_Sent:
  288.         case fsmACK_Sent:    /* Unexpected event? */
  289.             fsm_p->state =
  290.             (proc_request(fsm_p, &hdr, bufptr) == 0)
  291.                 ? fsmACK_Sent : fsmREQ_Sent;
  292.             break;
  293.  
  294.         case fsmACK_Rcvd:
  295.             if (proc_request(fsm_p, &hdr, bufptr) == 0) {
  296.                 fsm_tlu(fsm_p);
  297.             } else {
  298.                 /* give peer time to respond */
  299.                 fsm_timer(fsm_p);
  300.             }
  301.             break;
  302.  
  303.         case fsmCLOSED:
  304.             /* Don't accept any connections */
  305.             fsm_sendtermack(fsm_p, hdr.id);
  306.             /* We are attempting to close connection; */
  307.             /* wait for timeout to resend a Terminate Request */
  308.             /* fall thru */
  309.         default:    /* fsmCLOSING, fsmSTOPPING */
  310.             release(bufptr);
  311.         };
  312.         break;
  313.  
  314.     case CONFIG_ACK:
  315.         switch(fsm_p->state) {
  316.         case fsmREQ_Sent:
  317.         case fsmACK_Sent:
  318.             if (proc_ack(fsm_p, &hdr, bufptr) == 0) {
  319.                 fsm_p->retry = fsm_p->pdc.try_req;        /* initial restart counter */
  320.                 if (fsm_p->state == fsmREQ_Sent)
  321.                     fsm_p->state = fsmACK_Rcvd;
  322.                 else
  323.                     fsm_tlu(fsm_p);
  324.             }
  325.             break;
  326.  
  327.         case fsmOPENED:        /* Crossed connection? */
  328.             fsm_tld(fsm_p);
  329.             /* fallthru */
  330.         case fsmACK_Rcvd:    /* Crossed connection? */
  331.             release(bufptr);
  332.             fsm_sendreq(fsm_p);
  333.             fsm_p->state = fsmREQ_Sent;
  334.             break;
  335.  
  336.         case fsmCLOSED:
  337.         case fsmSTOPPED:
  338.             /* Out of Sync; kill the remote */
  339.             fsm_sendtermack(fsm_p, hdr.id);
  340.             /* fallthru */
  341.         default:    /* fsmCLOSING, fsmSTOPPING */
  342.             /* We are attempting to close connection; */
  343.             /* wait for timeout to resend a Terminate Request */
  344.             release(bufptr);
  345.         };
  346.         break;
  347.  
  348.     case CONFIG_NAK:
  349.     case CONFIG_REJ:
  350.         
  351.         switch(fsm_p->state) {
  352.         case fsmREQ_Sent:
  353.         case fsmACK_Sent:
  354.             fsm_p->retry = fsm_p->pdc.try_req;        /* initial restart counter */
  355.             /* Update our config request to reflect NAK/REJed options */
  356.             if (hdr.code == CONFIG_NAK)
  357.                 result = proc_nak(fsm_p, &hdr, bufptr);
  358.             else
  359.                 result = proc_reject(fsm_p, &hdr, bufptr);
  360.             if (result == 0)
  361.                 /* Send updated config request */
  362.                 fsm_sendreq(fsm_p);
  363.             break;
  364.  
  365.         case fsmOPENED:        /* Crossed connection? */
  366.             fsm_tld(fsm_p);
  367.             /* fallthru */
  368.         case fsmACK_Rcvd:    /* Crossed connection? */
  369.             release(bufptr);
  370.             fsm_sendreq(fsm_p);
  371.             fsm_p->state = fsmREQ_Sent;
  372.             break;
  373.  
  374.         case fsmCLOSED:
  375.         case fsmSTOPPED:
  376.             /* Out of Sync; kill the remote */
  377.             fsm_sendtermack(fsm_p, hdr.id);
  378.             /* fallthru */
  379.         default: /* fsmCLOSING, fsmSTOPPING */
  380.             /* We are attempting to close connection; */
  381.             /* wait for timeout to resend a Terminate Request */
  382.             release(bufptr);
  383.         };
  384.         break;
  385.  
  386.     case TERM_REQ:
  387.         release(bufptr);    /* release buffer */
  388.         switch(fsm_p->state) {
  389.         case fsmOPENED:
  390.             fsm_p->state=fsmSTOPPING;
  391.             fsm_tld(fsm_p);
  392.             fsm_sendtermack(fsm_p, hdr.id);
  393.             fsm_p->retry = 0;            /* zero restart counter */
  394.             fsm_timer(fsm_p);            /* restart the timer */
  395.             break;
  396.  
  397.         case fsmACK_Rcvd:
  398.         case fsmACK_Sent:
  399.             fsm_p->state = fsmREQ_Sent;
  400.             /* fallthru */
  401.         default:    /* REQ_Sent, CLOSED, STOPPED, CLOSING, STOPPING */
  402.             /* Unexpected, but make them happy */
  403.             fsm_sendtermack(fsm_p, hdr.id);
  404.         };
  405.         break;
  406.  
  407.     case TERM_ACK:
  408.         release(bufptr);    /* release buffer */
  409.         switch(fsm_p->state) {
  410.         case fsmCLOSING:
  411.             fsm_p->state = fsmCLOSED;
  412.             fsm_tlf(fsm_p);
  413.             break;
  414.         case fsmSTOPPING:
  415.             fsm_p->state = fsmSTOPPED;
  416.             fsm_tlf(fsm_p);
  417.             break;
  418.  
  419.         case fsmOPENED:
  420.             /* Remote host has abruptly closed connection */
  421.             fsm_tld(fsm_p);
  422.             fsm_sendreq(fsm_p);
  423.             fsm_p->state = fsmREQ_Sent;
  424.             break;
  425.  
  426.         case fsmACK_Rcvd:
  427.             fsm_p->state = fsmREQ_Sent;
  428.  
  429.         }
  430.         break;
  431.  
  432.     case CODE_REJ:
  433.     case PROT_REJ:        /* should add some code to see what was rejected */
  434.         release(bufptr);
  435.         if (fsm_p->state == fsmACK_Rcvd)
  436.                 fsm_p->state = fsmREQ_Sent;
  437.         break;
  438.  
  439.     case ECHO_REQ:
  440.         if (fsm_p->state == fsmOPENED)    /* should maybe check for looped request */
  441.             fsm_send( fsm_p, ECHO_REPLY, hdr.id, bufptr );
  442.         else
  443.             release(bufptr);    /* ignore */
  444.         break;
  445.  
  446.     case ECHO_REPLY:
  447.         fsm_p->lap->echo_count = 0;    /* reset echo counter */
  448.         /* fall thru */
  449.     case DISCARD_REQ:
  450.         release(bufptr);
  451.         break;
  452.  
  453.     default:
  454.         PPP_DEBUG_CHECKS("\pUnrecognized option type");
  455.         hdr.len += CONFIG_HDR_LEN;    /* restore length */
  456.         htoncnf( &hdr, bufptr );    /* put header back on */
  457.         fsm_send( fsm_p, CODE_REJ, hdr.id, bufptr );
  458.  
  459.         if (fsm_p->state == fsmOPENED) {
  460.             fsm_tld(fsm_p);
  461.             fsm_sendreq(fsm_p);
  462.             fsm_p->state = fsmREQ_Sent;
  463.         }
  464.     }
  465. }
  466.  
  467. /* Timeout while waiting for reply from remote host */
  468. static void
  469. fsm_timeout(void)
  470. {
  471.     struct TMtimer    *timerp;
  472.     struct fsm_s    *fsm_p;
  473.     
  474.     asm {
  475.             move.l    a1,timerp
  476.     }
  477.     fsm_p = timerp->fsm_p;
  478.  
  479.     switch(fsm_p->state) {
  480.     case fsmREQ_Sent:
  481.     case fsmACK_Rcvd:
  482.     case fsmACK_Sent:
  483.         if (fsm_p->retry > 0) {
  484.             fsm_sendreq(fsm_p);
  485.             fsm_p->state = (fsm_p->state == fsmACK_Sent ? fsmACK_Sent : fsmREQ_Sent);
  486.         } else {
  487.             fsm_p->state = fsmSTOPPED;
  488.             fsm_tlf(fsm_p);
  489.         }
  490.         break;
  491.  
  492.     case fsmCLOSING:
  493.     case fsmSTOPPING:
  494.         if (fsm_p->retry > 0) {
  495.             fsm_sendtermreq(fsm_p);
  496.         } else {
  497.             fsm_p->state = (fsm_p->state == fsmCLOSING ? fsmCLOSED : fsmSTOPPED);
  498.             fsm_tlf(fsm_p);
  499.         }
  500.         break;
  501.     }
  502. }
  503.  
  504. /************************************************************************/
  505. /*            A d m i n i s t r a t i v e    E v e n t s                    */
  506. /************************************************************************/
  507.  
  508. /* Up Event */
  509. void
  510. fsm_up(fsm_p)
  511. struct fsm_s *fsm_p;
  512. {
  513.     switch ( fsm_p->state ) {
  514.     case fsmSTARTING:
  515.         fsm_reset(fsm_p);        /* reset option values and the restart counter */
  516.         fsm_sendreq(fsm_p);
  517.         fsm_p->state = fsmREQ_Sent;
  518.         break;
  519.     case fsmINITIAL:
  520.         fsm_p->state = fsmCLOSED;
  521.     };
  522. }
  523.  
  524. /* Down Event */
  525. void
  526. fsm_down(fsm_p)
  527. struct fsm_s *fsm_p;
  528. {
  529.     switch ( fsm_p->state ) {
  530.     case fsmREQ_Sent:
  531.     case fsmACK_Rcvd:
  532.     case fsmACK_Sent:
  533.     case fsmSTOPPING:
  534.         stop_timer(&(fsm_p->timer));
  535.         fsm_p->state = fsmSTARTING;
  536.         break;
  537.  
  538.     case fsmOPENED:
  539.         fsm_p->state = fsmSTARTING;
  540.         fsm_tld(fsm_p);
  541.         break;
  542.     
  543.     case fsmSTOPPED:
  544.         fsm_p->state = fsmSTARTING;
  545.         fsm_tls(fsm_p);
  546.         break;
  547.         
  548.     case fsmCLOSING:
  549.         stop_timer(&(fsm_p->timer));
  550.     case fsmCLOSED:
  551.         fsm_p->state = fsmINITIAL;
  552.     }
  553. }
  554.  
  555. /* Open Event */
  556. void
  557. fsm_open(fsm_p)
  558. struct fsm_s *fsm_p;
  559. {
  560.     switch ( fsm_p->state ) {
  561.     case fsmINITIAL:
  562.         fsm_p->state = fsmSTARTING;        /* we are starting */
  563.         fsm_tls(fsm_p);
  564.         break;
  565.     case fsmCLOSED:
  566.         fsm_reset(fsm_p);            /* reset options and init restart counter */
  567.         fsm_sendreq(fsm_p);
  568.         fsm_p->state = fsmREQ_Sent;
  569.         break;
  570.     case fsmCLOSING:
  571.         fsm_p->state = fsmSTOPPING;
  572.         /* fallthru */
  573.     case fsmSTOPPED:
  574.     case fsmSTOPPING:
  575.         fsm_down(fsm_p);        /* Implement the restart option */
  576.         fsm_up(fsm_p);
  577.     };
  578. }
  579.  
  580. /* Close Event */
  581. void
  582. fsm_close(fsm_p)
  583. struct fsm_s *fsm_p;
  584. {
  585.     switch ( fsm_p->state ) {
  586.     case fsmOPENED:
  587.         fsm_tld(fsm_p);    
  588.         /* fallthru */
  589.     case fsmACK_Sent:
  590.     case fsmREQ_Sent:
  591.     case fsmACK_Rcvd:
  592.         fsm_p->retry = fsm_p->pdc.try_terminate;
  593.         fsm_sendtermreq(fsm_p);
  594.         /* fallthru */
  595.     case fsmSTOPPING:
  596.         fsm_p->state = fsmCLOSING;
  597.         break;
  598.  
  599.     case fsmSTOPPED:
  600.         fsm_p->state = fsmCLOSED;
  601.         break;
  602.     
  603.     case fsmSTARTING:
  604.         fsm_p->state = fsmINITIAL;
  605.         break;
  606.  
  607.     /* case fsmCLOSED:   nothing to do */
  608.     };
  609. }
  610.  
  611. /* Initialize the fsm for this protocol
  612.  * Called from protocol _init
  613.  */
  614. void
  615. fsm_init(struct fsm_s *fsm_p)
  616. {
  617.     fsm_p->state = fsmINITIAL;        /* initialize state */
  618. }
  619.  
  620. /* Reset the option variables, and retry counters */
  621. static void
  622. fsm_reset(struct fsm_s *fsm_p)
  623. {
  624.     LapInfo            *lap = fsm_p->lap;
  625.     struct proto_s    *proto_p = fsm_p->pdv;
  626.  
  627.     if (fsm_p->pdc.fsmi == Lcp) {
  628.         BlockMove(&(lap->configdata.lcpconf.local), &(proto_p->local),
  629.                     sizeof( struct lcp_will_want )); 
  630.         BlockMove(&(lap->configdata.lcpconf.remote), &(proto_p->remote),
  631.                     sizeof( struct lcp_will_want ));
  632.         BlockMove(lap->lcp_default_p, &(proto_p->remote.work.lcp_option),
  633.                     sizeof( struct lcp_value_s ));
  634.         lap->PPP_RecvACM = lap->PPP_XmitACM = LCP_ACCM_DEFAULT;
  635.         fsm_p->retry = lap->configdata.lcpconf.req_tries; /* reset retry counter (config reqs.) */
  636.         fsm_p->pdc.timeout = lap->configdata.lcpconf.timeout;
  637.     } else {    /* IPcp */
  638.         BlockMove(&(lap->configdata.ipcpconf.local), &(proto_p->local),
  639.                     sizeof( struct ipcp_will_want ));
  640.         BlockMove(&(lap->configdata.ipcpconf.remote), &(proto_p->remote),
  641.                     sizeof( struct ipcp_will_want ));
  642.         BlockMove(lap->ipcp_default_p, &(proto_p->remote.work.ipcp_option),
  643.                     sizeof( struct ipcp_value_s ));    
  644.         fsm_p->retry = lap->configdata.ipcpconf.req_tries; /* reset retry counter (config reqs.) */
  645.         fsm_p->pdc.timeout = lap->configdata.ipcpconf.timeout;
  646.     }
  647.     BlockMove(&(proto_p->local.want), &(proto_p->local.work),
  648.                 sizeof (union value_s ));
  649.     proto_p->local.work_negotiate = proto_p->local.want_negotiate;
  650.     proto_p->remote.work_negotiate = FALSE;
  651.     fsm_p->pdc.try_req = fsm_p->retry;
  652.     fsm_p->retry_nak = fsm_p->pdc.try_nak;    /* reset the try nak counter */
  653.     /* Initialize timer */
  654.     set_timer(&(fsm_p->timer), fsm_p, (void *) fsm_timeout);
  655. }